use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int};
use std::ptr;
use std::io::{self, stdout, Stdout};

use ratatui::{
    backend::CrosstermBackend,
    layout::{Constraint, Direction, Layout, Rect},
    style::{Color, Modifier, Style},
    text::{Line, Span, Text},
    widgets::{Block, Borders, Clear, Paragraph},
    Frame, Terminal,
};
use crossterm::{
    event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};

mod terminal;
mod widgets;
mod events;
mod layout;
mod style;
mod style_advanced;
mod backend;
mod performance;

pub use terminal::*;
pub use widgets::*;
pub use events::*;
pub use layout::*;
pub use style::*;
pub use style_advanced::*;
pub use backend::*;
pub use performance::*;

/// Result codes for FFI functions
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RatatuiResult {
    Ok = 0,
    ErrorNullPointer = -1,
    ErrorInvalidArgument = -2,
    ErrorMemoryAllocation = -3,
    ErrorTerminalInit = -4,
    ErrorTerminalDraw = -5,
    ErrorEventPoll = -6,
    ErrorUnknown = -99,
}

/// Convert Rust Result to C-compatible result code
pub fn result_to_code<T>(result: Result<T, Box<dyn std::error::Error>>) -> RatatuiResult {
    match result {
        Ok(_) => RatatuiResult::Ok,
        Err(_) => RatatuiResult::ErrorUnknown,
    }
}

/// Helper function to convert C string to Rust string
pub unsafe fn c_str_to_string(c_str: *const c_char) -> Result<String, RatatuiResult> {
    if c_str.is_null() {
        return Err(RatatuiResult::ErrorNullPointer);
    }

    match CStr::from_ptr(c_str).to_str() {
        Ok(s) => Ok(s.to_string()),
        Err(_) => Err(RatatuiResult::ErrorInvalidArgument),
    }
}

/// Helper function to convert Rust string to C string
pub fn string_to_c_str(s: &str) -> *mut c_char {
    match CString::new(s) {
        Ok(c_string) => c_string.into_raw(),
        Err(_) => ptr::null_mut(),
    }
}

/// Free a C string allocated by this library
#[no_mangle]
pub extern "C" fn ratatui_string_free(s: *mut c_char) {
    if !s.is_null() {
        unsafe {
            let _ = CString::from_raw(s);
        }
    }
}
